/*
 * check_vector.c
 *
 *  Created on: Sep 19, 2011
 *      Author: thienlong
 */

#include <check.h>
#include "../src/list.h"
#include <stdio.h>
vector *vec = NULL;

void setup() {
	vec = vector_new(0, int_eq_fn, mem_free, mem_storage_new(0, true), STACK_MEM);
}

void teardown() {
	printf("======goi teardown on vector's size = %d ====\n", vec->size);
	fflush(stdout);
	mem_storage_clear(vec->storage);
	vector_free_ref(&vec);
}

START_TEST(test_vector_new) {
	vector *v = vector_new(10, int_eq_fn, mem_free, NULL, 0);
	fail_unless(v->capacity == 10, "capacity sai rui");
	fail_unless(v->items != NULL, NULL);
	int i = 0;
	for (;i < 10; ++i) {
		fail_unless(v->items[i] == NULL, NULL);
	}
	fail_unless(v->delfn == mem_free, NULL);
	fail_unless(v->eqfn == int_eq_fn, NULL);
	vector_free(&v);
	fail_unless(v == NULL);
}
END_TEST

START_TEST(test_vector_new_neg) {
	vector *v = vector_new(-9, int_eq_fn, mem_free, NULL, 0);
	fail_unless(v->capacity == 16, "capacity sai rui");
	fail_unless(v->items != NULL, NULL);
	int i = 0;
	for (;i < 10; ++i) {
		fail_unless(v->items[i] == NULL, NULL);
	}
	fail_unless(v->delfn == mem_free, NULL);
	fail_unless(v->eqfn == int_eq_fn, NULL);
	vector_free(&v);
	fail_unless(v == NULL);
}
END_TEST

START_TEST(test_vector_new_zero) {
	vector *v = vector_new(0, int_eq_fn, mem_free, NULL, 0);
	fail_unless(v->capacity == 16, "capacity sai rui");
	fail_unless(v->items != NULL, NULL);
	int i = 0;
	for (;i < 10; ++i) {
		fail_unless(v->items[i] == NULL, NULL);
	}
	fail_unless(v->delfn == mem_free, NULL);
	fail_unless(v->eqfn == int_eq_fn, NULL);
	vector_free(&v);
	fail_unless(v == NULL);
}
END_TEST

START_TEST(test_vector_add) {
	fail_unless(vec != NULL, NULL);
	int *x = malloc(sizeof(int));
	*x = 100;
	vector_add(vec, x);
	fail_unless(vec->capacity == 16, NULL);
	fail_unless(vec->size == 1, NULL);
	fail_unless(vec->items[0] != NULL, NULL);
	fail_unless(vec->items[1] == NULL, NULL);
	int *y = vector_get(vec, 0);
	fail_unless(*y == 100, NULL);
	vector_add(vec, y);
	vector_add(vec, y);
	vector_add(vec, y);
	fail_unless(vec->size == 4, NULL);
	int *z = vector_get(vec, 3);
	fail_unless(*z == 100, NULL);
	fail_unless(x == y && y == z, NULL);
	z = malloc(sizeof(int));
	*z = -1;
	vector_add(vec, z);
	fail_unless(vec->size == 5, NULL);
	x = vector_get(vec, 4);
	fail_unless(*x == -1, NULL);
	fail_unless(vector_detach_ref(vec, y) == true, NULL);
	free(y);
}
END_TEST

START_TEST(test_vector_remove) {
	int *x = malloc(sizeof(int));
	int *y = malloc(sizeof(int));
	int *z = malloc(sizeof(int));
	int *t = malloc(sizeof(int));
	*x = 10;
	*y = -1;
	*z = 10;
	*t = 5;
	vector_add(vec, x);
	vector_add(vec, y);
	vector_add(vec, z);
	vector_add(vec, t);
	int index = vector_first(vec, z);
	fail_unless(index == 0, NULL);
	index = vector_first(vec, x);
	fail_unless(index == 0, NULL);
	index = vector_last(vec, z);
	fail_unless(index == 2, NULL);
	index = vector_last(vec, x);
	fail_unless(index == 2, NULL);
	fail_unless(vector_detach_ref(vec, z) == true, NULL);
	fail_unless(vec->size == 3, NULL);
	fail_unless(vec->items[0] != z, NULL);
	fail_unless(*((int*)vector_get(vec, 0)) == *z, NULL);
	vector_insert(vec, 2, z);
	int *a = vector_del(vec, 2);
	fail_unless(*a == 10, NULL);
	fail_unless(vec->size == 3, NULL);
	fail_unless(a == z, NULL);
	int *tmp = vector_get(vec, 2);
	fail_unless(*tmp == 5, NULL);
	int *b = vector_pop(vec);
	fail_unless(*b == 5, NULL);
	fail_unless(vec->size == 2, NULL);
	fail_unless(vector_remove(vec, a) == true, NULL);
	fail_unless(vec->size == 1, NULL);
	fail_unless(*((int *)vec->items[0]) == -1, NULL);
	vector_insert(vec, 0, a);
	fail_unless(vec->size == 2, NULL);
	fail_unless(*((int*) vec->items[0]) == 10, NULL);
	fail_unless(*((int *)vec->items[1]) == -1, NULL);
	int *c = vector_set(vec, 0, b);
	fail_unless(*c == 10, NULL);
	fail_unless(*((int*) vec->items[0]) == 5, NULL);
}
END_TEST

Suite * vector_suite() {
	Suite *s = suite_create("vector");
	TCase *tc_core = tcase_create("core");
	tcase_add_test(tc_core, test_vector_add);
	tcase_add_test(tc_core, test_vector_remove);
	tcase_add_test(tc_core, test_vector_new);
	tcase_add_checked_fixture(tc_core, setup, teardown);
	suite_add_tcase(s, tc_core);
	TCase *tc_limit = tcase_create("limits");
	tcase_add_test(tc_limit, test_vector_new_neg);
	tcase_add_test(tc_limit, test_vector_new_zero);
	suite_add_tcase(s, tc_limit);
	return s;
}

int
main (void)
{
  int number_failed = 0;
  Suite *s = vector_suite();
  SRunner *sr = srunner_create(s);
  srunner_set_fork_status(sr, CK_NOFORK);
  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);
  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
